package it.csi.finregio.finreges.client.services;

import it.crp.crparch.web.struts.service.CRPStrutsService;
import it.crp.crparch.web.struts.service.WebServiceException;
import it.crp.exception.ServiceException;
import it.crp.logger.PrdLoggerFactory;
import it.csi.finregio.finreges.client.ServiceLocator;
import it.csi.finregio.finreges.client.printers.PdfPrinter;
import it.csi.finregio.finreges.client.printers.Printer;
import it.csi.finregio.finreges.dto.DestinatarioScheda;
import it.csi.finregio.finreges.dto.EnteScheda;
import it.csi.finregio.finreges.dto.NotaScadenza;
import it.csi.finregio.finreges.dto.Riferimento;
import it.csi.finregio.finreges.dto.Scheda;
import it.csi.finregio.finreges.integration.SchedaService;
import it.csi.finregio.finreges.presentation.form.SchedaForm;
import it.csi.finregio.finreges.presentation.streaminfo.AbstractStreamInfo;
import it.csi.finregio.finreges.presentation.streaminfo.PdfStreamInfo;
import it.csi.finregio.finreges.util.SchedaData;
import it.csi.finregio.finreric.dto.ViewSearchScheda;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.html.simpleparser.HTMLWorker;
import com.lowagie.text.pdf.PdfWriter;

public class PrintService implements CRPStrutsService {

	private static final String DEFAULT_STREAM_CLASS = PdfStreamInfo.class.getName();

	private static final String DEFAULT_PRINTER_CLASS = PdfPrinter.class.getName();

	private Logger log = PrdLoggerFactory.getInstance().getLogger("finreges");

	/**
	 * Definisce il nome della classe che gestisce lo stream da inviare al client
	 */
	private String streamClass = DEFAULT_STREAM_CLASS;
	/**
	 * Il filename da inviare al browser
	 */
	private String fileName ;
	
	/**
	 * Nome della classe delegata alla stampa
	 */
	private String printerClass = DEFAULT_PRINTER_CLASS;
	
	/**
	 * Questo metodo deve restituire un oggetto di tipo StreamInfo
	 */

	public Object execute(ActionForm form) throws WebServiceException {
		log.info("[PrintService::execute] BEGIN");
		HttpServletRequest request = ((SchedaForm) form).getRequest();
		Collection result = (Collection) request.getAttribute("results");
		Collection dataToPrint = new ArrayList();
		log.info("[PrintService::execute()] Stream class: "+getStreamClass());
		try {
			SchedaService ss = new ServiceLocator().getSchedaService();
			for (Iterator iterator = result.iterator(); iterator.hasNext();) {
				ViewSearchScheda vss = (ViewSearchScheda) iterator.next();
				String idScheda = vss.getIdScheda();
				log.debug("[PrintService::execute] Ricerca dati idScheda: "
						+ idScheda);
				Scheda scheda = ss.findSchedaByIdScheda(idScheda);
				log.debug("[PrintService::execute] Scheda caricata: " + scheda);
				Riferimento[] rif = ss.findRiferimentoByIdScheda(idScheda);
				log
						.debug("[PrintService::execute] Numero riferimenti trovati: "
								+ (rif == null ? 0 : rif.length));
				DestinatarioScheda destinatario = ss
						.findDestinatarioByIdScheda(idScheda);
				log.debug("[PrintService::execute] Destinatario della scheda: "
						+ destinatario);
				NotaScadenza notaScadenza = ss
						.findNotaScadenzaByIdScheda(idScheda);
				log
						.debug("[PrintService::execute] Nota scadenza della scheda: "
								+ notaScadenza);
				EnteScheda[] enteSchedas = ss
						.findEnteSchedaByIdScheda(idScheda);
				log.debug("[PrintService::execute] Numero enti trovati: "
						+ (enteSchedas == null ? 0 : enteSchedas.length));
				SchedaData data = new SchedaData(scheda, rif, destinatario,
						notaScadenza, enteSchedas);
				dataToPrint.add(data);
			}
			Printer printer = (Printer) Class.forName(getPrinterClass()).newInstance();
			InputStream in = printer.print(dataToPrint);
			
			Class streamInfoClass = Class.forName(getStreamClass());
			Constructor constructor = streamInfoClass.getConstructor(new Class[]{InputStream.class});
			AbstractStreamInfo streamInfo = (AbstractStreamInfo) constructor.newInstance(new Object[]{in});
			streamInfo.setFileName(getFileName());
//			PdfStreamInfo streamInfo = new PdfStreamInfo(
//					new ByteArrayInputStream(bout.toByteArray()));
			return streamInfo;
		} catch (ServiceException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (DocumentException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (IOException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (ClassNotFoundException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (SecurityException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (NoSuchMethodException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (IllegalArgumentException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (InstantiationException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (IllegalAccessException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (InvocationTargetException e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		} catch (Exception e) {
			log.error("[PrintService::execute]  " + e.getMessage(), e);
			throw new WebServiceException(e.getMessage());
		}

	}
	public String getStreamClass() {
		return streamClass;
	}
	public void setStreamClass(String streamClass) {
		this.streamClass = streamClass;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public String getPrinterClass() {
		return printerClass;
	}
	public void setPrinterClass(String printerClass) {
		this.printerClass = printerClass;
	}

}
